#include "mainwindow.h"
#include "login_page.h"
#include "profile.h"

#include <QStandardItemModel>
#include <QDebug>
#include <QLabel>
#include <QTabBar>
#include <QDir>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QStackedWidget>
#include <QStatusBar>
#include <QVBoxLayout>
#include <QDateTime>
#include <QMessageBox>
#include <memory>
#include <qdatetime.h>
#include <qnamespace.h>



#include "ElaContentDialog.h"
#include "ElaDockWidget.h"
#include "ElaEventBus.h"
#include "ElaPushButton.h"
#include "ElaMenu.h"
#include "ElaMenuBar.h"
#include "ElaProgressBar.h"
#include "ElaStatusBar.h"
#include "ElaText.h"
#include "ElaListView.h"
#include "ElaToolBar.h"
#include "ElaToolButton.h"
#include "ElaMessageBar.h"

#include "ai_recognition.h"

#ifdef Q_OS_WIN
#endif

#ifndef __USE_CUDA_WARD_SENSE__
#error "__USE_CUDA_WARD_SENSE__ 没有定义！"
#endif


//#include "ElaCheckBox.h"

// TODO: distinguish init of ui and init of functional member(controller/videostream/etc)

MainWindow::MainWindow(QWidget* parent)
    : ElaWindow(parent), video_running(false), audio_running(false)
{
    row = 0;
    initWindow();
    // setWindowModality(Qt::ApplicationModal);
    //ElaCheckBox *box = new ElaCheckBox("记住账号",this);
    //box->move(130,155);
    initEdgeLayout();

    //中心窗口
    initContent();

    setNavigationBarDisplayMode(ElaNavigationType::Compact);

// 拦截默认关闭事件
    _closeDialog = new ElaContentDialog(this);
    connect(_closeDialog, &ElaContentDialog::rightButtonClicked, this, &MainWindow::myCloseWindow);
    connect(_closeDialog, &ElaContentDialog::middleButtonClicked, this, [=]() {
        _closeDialog->close();
        showMinimized();
    });
    this->setIsDefaultClosed(false);
    connect(this, &MainWindow::closeButtonClicked, this, [=]() {
        _closeDialog->exec();
    });

    // // ********** start video **********
    // video_start();

    // setWindowTitle("欢迎登陆");     //设置窗口标题
    // setFixedSize(400,300);     //设置窗口固定尺寸，使得窗口大小固定

    //QPushButton *button = new QPushButton;//(两个参数：文本和父类指针，按控件大小来创建窗口)
    //button->show();      //show以顶层方式弹出窗口控件
    //让button对象依赖在窗口中
    //button->setParent(this);
    //button->setText("First_Button");
    //button->move(100,0);      //移动，参数两个，移动的距离（距离左边和上边）

    moveToCenter();
}

void MainWindow::initWindow()
{
    profile *p =new profile();
    p->setWindowModality(Qt::ApplicationModal);

    /*判断文件夹中有没有病人资料文件夹*/
    QDir dir(p->filePath);

    if(!dir.exists())
    {
        qDebug() << "文件夹不存在！";
        dir.cd("../");
        if(dir.mkdir("patients")) {
            qDebug() << "文件夹创建成功！";
            dir.cd("patients");
            dir.mkdir("patient");
            dir.mkdir("document");
        } else {
            qDebug()<<"文件夹创建失败！";
        }
    }
    // setIsEnableMica(true);
    // setIsCentralStackedWidgetTransparent(true);
    // screenshot_20012025_171327.jpg
    setWindowIcon(QIcon(":/include/Image/ward-sense-logo.png"));
    resize(1200, 740);
    // ElaLog::getInstance()->initMessageLog(true);
    ElaTheme::getInstance()->setThemeMode(ElaThemeType::Dark);
    
    // setIsNavigationBarEnable(false);
    // setNavigationBarDisplayMode(ElaNavigationType::Compact);
    // setWindowButtonFlag(ElaAppBarType::MinimizeButtonHint, false);
    setUserInfoCardPixmap(QPixmap(":/Resource/Image/Cirno.jpg"));
    setUserInfoCardTitle("登陆");
    setUserInfoCardSubTitle("登陆使用更多功能");
    setWindowTitle("WardSense");
    // setUserInfoCardPixmap(icon00);

    // setIsStayTop(true);
    // setUserInfoCardVisible(false);
}

MainWindow::~MainWindow() {}

void MainWindow::initEdgeLayout()
{  
    profile *p =new profile();
    p->setWindowModality(Qt::ApplicationModal);
    /*更改资料卡颜色*/

    connect(eTheme,&ElaTheme::themeModeChanged,p,[=](){
        qDebug()<<"颜色改变了！";
        if(p->color == 0)
        {
           p->color = 1;
           if(p->color == 0)
            {
              p->setStyleSheet("background-color: #333333; color: white;");
            }
            else
            {
              p->setStyleSheet("color:black");
            }
        }
        else
        {
            p->color = 0;
            if(p->color == 0)
            {
              p->setStyleSheet("background-color: #333333; color: white;");
            }
            else
            {
              p->setStyleSheet("color:black");
            }
        }
    });
    // ********** menu(on the top middle)     **********
    QWidget* customWidget = new QWidget(this);
    QVBoxLayout* customLayout = new QVBoxLayout(customWidget);
    customLayout->setContentsMargins(0, 0, 0, 0);
    customLayout->addStretch();
    this->setCustomWidget(ElaAppBarType::MiddleArea, customWidget);
    this->setCustomWidgetMaximumWidth(500);

    // ********** tool bar(on the top left) **********
    ElaToolBar* toolBar = new ElaToolBar("tool bar", this);
    toolBar->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
    toolBar->setToolBarSpacing(3);
    toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
    toolBar->setIconSize(QSize(25, 25));
    // toolBar->setFloatable(false);
    // toolBar->setMovable(false);

    this->addToolBar(Qt::TopToolBarArea, toolBar);

    ElaToolButton* toolButton_patient_profile = new ElaToolButton(this);
    toolButton_patient_profile->setElaIcon(ElaIconType::CreditCardFront);
    toolBar->addWidget(toolButton_patient_profile);
    toolBar->addSeparator();

    connect(toolButton_patient_profile,&ElaToolButton::clicked,this,[=](){
        p->move(100,100);
        p->show();
        QDateTime currentDateTime = QDateTime::currentDateTime();
        QString formattedDateTime = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
        p->Time = formattedDateTime;
    });

    progressBar = new CustomProgressBar(this);
    progressBar->setMinimum(0);
    progressBar->setMaximum(0);
    progressBar->setFixedWidth(350);
    toolBar->addWidget(progressBar);

    //停靠窗口
    ElaListView *listView0 = new ElaListView(this);
    ElaListView *listView1 = new ElaListView(this);
    listView0->setEditTriggers(QAbstractItemView::NoEditTriggers);
    listView1->setEditTriggers(QAbstractItemView::NoEditTriggers);
    // 创建数据模型
    QStandardItemModel *model0 = new QStandardItemModel(this); // 4行3列
    listView0->setModel(model0);
    QStandardItemModel *model1 = new QStandardItemModel(this); // 4行3列
    listView1->setModel(model1);

    // ********** dock(on the right) **********
    ElaDockWidget* logDockWidget = new ElaDockWidget("消息", this);
    logDockWidget->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
    this->addDockWidget(Qt::RightDockWidgetArea, logDockWidget);
    resizeDocks({logDockWidget}, {200}, Qt::Horizontal);
    logDockWidget->setWidget(listView0);

    ElaDockWidget* updateDockWidget = new ElaDockWidget("已读消息", this);
    updateDockWidget->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
    this->addDockWidget(Qt::RightDockWidgetArea, updateDockWidget);
    tabifyDockWidget(logDockWidget,updateDockWidget);
    resizeDocks({updateDockWidget}, {200}, Qt::Horizontal);
    updateDockWidget->setWidget(listView1);
    setDockNestingEnabled(true);

    connect(toolButton_patient_profile,&ElaToolButton::clicked,this,[=](){
        QDateTime currentDateTime = QDateTime::currentDateTime();
        QString formattedDateTime = currentDateTime.toString("yyyy-MM-dd hh:mm:ss");
        ElaMessageBar::information(ElaMessageBarType::BottomRight,"提示", "您有一条新消息!", 2000);
        QStandardItem *item = new QStandardItem( formattedDateTime+"  病人出现了辱骂的行为");
        model0->appendRow(item);
    });

    connect(listView0,&ElaListView::clicked,this,[=](const QModelIndex &index){
        p->move(100,100);
        p->show();
        row = index.row();
        information = model0->data(index, Qt::DisplayRole).toString();
        p->Time = information.left(19);
    });

    connect(p,&profile::proFileClosed,this,[=](){
        qDebug()<<p->deleteflag;
        if(p->deleteflag == 1)
        {
            QStandardItem *readItem = new QStandardItem(information);
            model0->removeRow(row);
            model1->appendRow(readItem);
            p->deleteflag = 0;
        }
    });

    // ********** status bar(on the bottom) **********
    ElaStatusBar* statusBar = new ElaStatusBar(this);
    ElaText* statusText = new ElaText("初始化成功！", this);
    statusText->setTextPixelSize(14);
    statusBar->addWidget(statusText);
    this->setStatusBar(statusBar);
}

void MainWindow::initContent()
{
    controller = std::make_unique<LogicThread>();
#ifdef __USE_CUDA_WARD_SENSE__
    ModelLoaderThread *loaderThread = new ModelLoaderThread(this,
        { .modelPath = "resource/model/act.onnx", });
    loaderThread->start();

    whisper = std::make_unique<Whisper>();
#endif
    controller->start();
    progressBar->running();

    HttpServerThread* serverThread = new HttpServerThread();
    serverThread->start();  // 启动线程

    // _homePage = new T_Home(this);
    // addPageNode("HOME", _homePage, ElaIconType::House);

    _graphicsPage = new WardGraphics(this);
    addPageNode("主预览", _graphicsPage, 9, ElaIconType::CameraViewfinder);

    // _popupPage = new T_Popup(this);
    // addPageNode("事件记录", _popupPage, ElaIconType::Envelope);

    _playerPage = new T_Player(this);
    addPageNode("视频分析", _playerPage, ElaIconType::ClapperboardPlay);

    addFooterNode("Login", nullptr, _loginpage_key, 0, ElaIconType::User);
    _loginpage = new LoginPage();

    // test add subtitle
    SubtitleItem item;
    item.timestamp = QDateTime::fromString("2025-01-01T00:00:00.000Z", "yyyy-MM-ddThh:mm:ss.zzzZ");
    item.content = "这是一个测试字幕";
    AIRecogManager::getInstance().addAudioRecognition(item);
    AIRecogManager::getInstance().addAudioRecognition({item.timestamp.addSecs(20), "这是一个测试字幕"});
    AIRecogManager::getInstance().addAudioRecognition({item.timestamp.addSecs(40), "这是一个测试字幕"});
    AIRecogManager::getInstance().addAudioRecognition({item.timestamp.addSecs(60), "这是一个测试字幕"});
    AIRecogManager::getInstance().addAudioRecognition({item.timestamp.addSecs(80), "这是一个测试字幕"});
    AIRecogManager::getInstance().addAudioRecognition({item.timestamp.addSecs(100), "这是一个测试字幕"});

    this->setUserInfoCardVisible(false);

    _loginpage->hide();
    connect(_loginpage, &LoginPage::windowClosed, this, [=](){
        //qDebug()<<"触发";
        this->close();
    });
    connect(this, &ElaWindow::navigationNodeClicked, this, [=](ElaNavigationType::NavigationNodeType nodeType, QString nodeKey) {
        if (_loginpage_key == nodeKey) {
            if(_loginpage->flag == 0)
            {
                _loginpage->setFixedSize(400, 400);
                _loginpage->moveToCenter();
                _loginpage->show();
            }
           else
           {
               _loginpage->Xiaoxi();
           } 
        }
    });

    _caseinformationPage = new T_CaseInformation(this);
    addPageNode("患者信息", _caseinformationPage, 0, ElaIconType::AddressCard);
    video_init();
    audio_init();

    // signal & slot
    connect(this, &MainWindow::userInfoCardClicked, this, [=]() {
        if(_loginpage->flag == 0)
        {
            _loginpage->setFixedSize(400, 400);
            _loginpage->moveToCenter();
            _loginpage->show();
        }
        else
        {
            _loginpage->Xiaoxi();
        }

    });

    // signal & slot
    connect(controller.get(), &LogicThread::frameReady, _graphicsPage, &WardGraphics::pic_update);
#ifdef __USE_CUDA_WARD_SENSE__
    qRegisterMetaType<SegmentResult>("SegmentResult");
    qRegisterMetaType<QList<SegmentResult>>("QList<SegmentResult>");
    connect(loaderThread, &ModelLoaderThread::modelLoaded, this->progressBar, &CustomProgressBar::done);
    connect(loaderThread, &ModelLoaderThread::modelLoaded, this->whisper.get(), &Whisper::initializeModel);
    connect(whisper->m_worker, &WhisperWorker::initializationFinished,
            this, &MainWindow::handleWhisperInit, Qt::QueuedConnection);
    connect(whisper->m_worker, &WhisperWorker::audioProcessingFinished,
            this, &MainWindow::handleWhisperResult, Qt::QueuedConnection);
    connect(this, &MainWindow::startProcessing, whisper->m_worker,
            &WhisperWorker::processAudio, Qt::QueuedConnection);
    if (whisper && whisper->m_worker) {
        connect(whisper->m_worker, &WhisperWorker::errorOccurred, this, [](const QString& msg) {
            QMessageBox::critical(nullptr, "错误", msg);
            });
    }
#endif
}

#ifdef __USE_CUDA_WARD_SENSE__
void MainWindow::handleWhisperInit(bool res)
{
    // std::cout << "whisper init " << (res ? "success" : "failed") << std::endl;

    // INFO: for test
    // emit startProcessing("data/jfk.wav");
}

// 转换函数
static SubtitleItem convertToSubtitleItem(const SegmentResult& segment) {
    SubtitleItem item;
    item.timestamp = QDateTime::fromString(segment.startTime, "yyyy-MM-dd hh:mm:ss.zzz"); // 使用 startTime 作为时间戳
    item.content = segment.speaker + "：" + segment.text; // 拼接说话人和文本
    return item;
}

void MainWindow::handleWhisperResult(const QList<SegmentResult>& results)
{
    // std::cout << "whisper process finished" << std::endl;
    std::cout << results[0].text.toStdString() << std::endl;
    // _graphicsPage->caption_list->m_data.append({})
    for (auto &it : results) {
        SubtitleItem item = convertToSubtitleItem(it);
        // _graphicsPage->caption_list->m_data.append(item);
        AIRecogManager::getInstance().addAudioRecognition(item);
        _graphicsPage->caption_list->appendData(item); // 使用模型的安全插入方法
    }
}
#endif
void MainWindow::myCloseWindow()
{
    if (audio_saving)
    {
        stop_audio_saving();
    }
    if (video_saving)
    {
        stop_video_saving();
    }
    if (audio_running)
    {
        close_audio();
    }
    if (video_running)
    {
        close_video();
    }
    closeWindow();
}

int MainWindow::video_init(/*ElaWindow *w*/)
{
    video_saving = false;
    // this->vid_vec.push_back(std::make_unique<VideoStreamThread>("rtsp://127.0.0.1:8554/stream", 0, nullptr));
    this->vid_vec.push_back(std::make_unique<VideoStreamThread>("rtsp://admin:spark@123456@192.168.31.36", 0, nullptr));
    this->vid_vec.push_back(std::make_unique<VideoStreamThread>("rtsp://admin:spark@123456@192.168.31.36", 1, nullptr));
    this->vid_vec.push_back(std::make_unique<VideoStreamThread>("rtsp://admin:spark@123456@192.168.31.139", 2, nullptr));
    this->vid_vec.push_back(std::make_unique<VideoStreamThread>("rtsp://admin:spark@123456@192.168.31.139", 3, nullptr));

    stream_save_vec.push_back(std::make_unique<StreamSaveThread>(0, nullptr));
    stream_save_vec.push_back(std::make_unique<StreamSaveThread>(1, nullptr));
    stream_save_vec.push_back(std::make_unique<StreamSaveThread>(2, nullptr));
    stream_save_vec.push_back(std::make_unique<StreamSaveThread>(3, nullptr));

    return 0;
}

int MainWindow::open_video()
{
    if (video_running)
        return 0;

    video_running = true;

    for (auto& it : vid_vec)
        it->start();

    for (auto& it : aud_vec)
        it->audio_start();
    for (auto& it : aud_ctrl_vec)
        it->audio_ctrl_start();

    return 0;
}

void MainWindow::close_video()
{
    video_running = false;
    for (auto& it : vid_vec)
        it->stop();

    for (auto &it : aud_ctrl_vec)
        it->audio_ctrl_stop();
    for (auto &it : aud_vec)
        it->audio_stop();

}

void MainWindow::toggle_video_display()
{
    qDebug() << "toggle video display, running: " << video_running;
    if (video_running) {
        if (video_saving) {
            ElaMessageBar::warning(ElaMessageBarType::BottomRight,"提示", "自动停止录制!", 2000);
            stop_video_saving();
        }

        close_video();
    } else {
        open_video();
    }
}

int MainWindow::start_video_saving()
{
	video_saving = true;
    for (auto &it : vid_vec)
        it->video_mux_start();
    for (auto &it : aud_ctrl_vec)
        it->audio_mux_start();
    for (auto &it : stream_save_vec)
        it->stream_save_start();

    return 0;
}

int MainWindow::stop_video_saving()
{
	video_saving = false;
    for (auto &it : stream_save_vec)
        it->stream_save_stop();
    for (auto &it : vid_vec)
        it->video_mux_stop();
    for (auto &it : aud_ctrl_vec)
        it->audio_mux_stop();

    return 0;
}

// cannot toggle too fast. Starting/Stopping the record while stopping/starting operations is
// not completed will crash
void MainWindow::toggle_video_saving(bool checked)
{
    qDebug() << "toggle video saving, saving: " << video_saving;
    qDebug() << "checked: " << checked;
    if (video_saving && !checked) {
        ElaMessageBar::success(ElaMessageBarType::BottomRight,"提示", "停止录制", 1000);
        stop_video_saving();
    } else if (!video_saving && checked) {
        if (!video_running) {
            ElaMessageBar::warning(ElaMessageBarType::BottomRight,"提示", "未打开视频流!", 2000);
            return;
        }

        ElaMessageBar::success(ElaMessageBarType::BottomRight,"提示", "开始录制", 1000);
        start_video_saving();
    }
}

int MainWindow::audio_init()
{
    audio_saving = false;
    // this->vid_vec.push_back(std::make_unique<VideoStreamThread>("rtsp://127.0.0.1:8554/stream", 0, nullptr));
    this->aud_vec.push_back(std::make_unique<AudioThread>("rtsp://admin:spark@123456@192.168.31.36", 0, nullptr));
    this->aud_vec.push_back(std::make_unique<AudioThread>("rtsp://admin:spark@123456@192.168.31.36", 1, nullptr));
    this->aud_vec.push_back(std::make_unique<AudioThread>("rtsp://admin:spark@123456@192.168.31.139", 2, nullptr));
    this->aud_vec.push_back(std::make_unique<AudioThread>("rtsp://admin:spark@123456@192.168.31.139", 3, nullptr));

    aud_ctrl_vec.push_back(std::make_unique<AudioCtrlThread>(0, nullptr));
    aud_ctrl_vec.push_back(std::make_unique<AudioCtrlThread>(1, nullptr));
    aud_ctrl_vec.push_back(std::make_unique<AudioCtrlThread>(2, nullptr));
    aud_ctrl_vec.push_back(std::make_unique<AudioCtrlThread>(3, nullptr));
    
    aud_play_vec.push_back(std::make_unique<AudioPlayThread>(0, nullptr));
    aud_play_vec.push_back(std::make_unique<AudioPlayThread>(1, nullptr));
    aud_play_vec.push_back(std::make_unique<AudioPlayThread>(2, nullptr));
    aud_play_vec.push_back(std::make_unique<AudioPlayThread>(3, nullptr));

    aud_auto_save_vec.push_back(std::make_unique<AudioAutoSaveThread>(0, nullptr));
    aud_auto_save_vec.push_back(std::make_unique<AudioAutoSaveThread>(1, nullptr));
    aud_auto_save_vec.push_back(std::make_unique<AudioAutoSaveThread>(2, nullptr));
    aud_auto_save_vec.push_back(std::make_unique<AudioAutoSaveThread>(3, nullptr));

#ifdef __USE_CUDA_WARD_SENSE__
    connect(aud_auto_save_vec[0].get(), &AudioAutoSaveThread::startProcessing, whisper->m_worker,
            &WhisperWorker::processAudio, Qt::QueuedConnection);
#endif

    return 0;
}

int MainWindow::open_audio()
{
    if (audio_running)
        return 0;

    std::cout << "open audio" << std::endl;

    audio_running = true;

    for (auto& it : aud_ctrl_vec)
        it->audio_play_start();
    for (auto& it : aud_play_vec)
        it->audio_play_start();

    return 0;
}

void MainWindow::close_audio()
{
    std::cout << "close audio" << std::endl;

	audio_running = false;

    for (auto &it : aud_play_vec)
        it->audio_play_stop();
    for (auto &it : aud_ctrl_vec)
        it->audio_play_stop();

}

void MainWindow::toggle_audio_display()
{
    qDebug() << "toggle audio display, running: " << audio_running;
    if (audio_running)
        close_audio();
    else
        open_audio();
}


int MainWindow::start_audio_saving()
{
    std::cout << "save audio" << std::endl;

	audio_saving = true;
    for (auto &it : aud_ctrl_vec)
        it->audio_auto_save_start();
    for (auto &it : aud_auto_save_vec)
        it->audio_auto_save_start();

    return 0;
}

int MainWindow::stop_audio_saving()
{
    std::cout << "stop saving audio" << std::endl;

	audio_saving = false;
    for (auto &it : aud_auto_save_vec)
        it->audio_auto_save_stop();
    for (auto &it : aud_ctrl_vec)
        it->audio_auto_save_stop();

    return 0;
}

// FIX:
// 1. cannot close human talk detect when video is not playing
// 2. cannot toggle too fast
void MainWindow::toggle_talking_detect()
{
    qDebug() << "toggle audio saving, saving: " << audio_saving;
    if (audio_saving) {
        ElaMessageBar::information(ElaMessageBarType::BottomRight,"提示", "关闭语音识别", 1000);
        stop_audio_saving();
    } else {
        ElaMessageBar::information(ElaMessageBarType::BottomRight,"提示", "开启语音识别", 1000);
        start_audio_saving();
    }
}

Whisper* MainWindow::getWhisper() {
    return whisper.get();
}

void MainWindow::onLoginWindowClosed()
{
    qDebug() << "子窗口已关闭，主窗口即将退出";
    this->close();  // 关闭主窗口
}
